<template>
  <!-- 音乐播放控制器 -->
  <div class="music_control">
    <div class="main">
      <div class="pic" v-if="Object.keys(songDetail).length !== 0">
        <img
          :src="songDetail.al.picUrl"
          alt=""
          class="pic_url"
          @click="goToLyric"
        />
        <div class="name_ar">
          <div class="name">{{ songDetail.name }}</div>
          <div class="ar">
            {{ songDetail.ar.map((item) => item.name).join("/") }}
          </div>
        </div>
      </div>
      <div class="process">
        <div class="control">
          <span class="prev" @click="prevClick"></span>
          <span class="play" @click="btnClick">{{ playIcon }}</span>
          <span class="next" @click="nextClick"></span>
        </div>
        <div class="process_bar" ref="processBar" @click="processBarClick">
          <div class="process_bar_child" ref="processBarChild">
            <div
              class="circule"
              @mousedown="circuleMouseDown"
              ref="circule"
            ></div>
          </div>
        </div>

        <div class="music_time">
          <div class="now_time">{{ nowTime }}</div>
          /
          <div class="all_time">{{ allTime }}</div>
        </div>
      </div>
      <div class="method">
        <span class="func" @click="funcClick" :title="funcIcon.key">{{
          funcIcon.value
        }}</span>
        <span class="music_list" @click="musicListClick"></span>
        <div class="volume">
          <span class="volume_icon"></span>
          <div class="volume_bar" ref="volumeBar" @click="volumeBarClick">
            <div class="volume_bar_child" ref="volumeBarChild">
              <div
                class="volume_circule"
                ref="volumeCircule"
                @mousedown="volumeCirculeMousedown"
              ></div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <audio
      id="audio"
      ref="audio"
      @timeupdate="audioTimeUpdate"
      @ended="audioEnded"
      :key="id"
    >
      <source
        :src="
          id === 0
            ? ''
            : `https://music.163.com/song/media/outer/url?id=${currentPlaySong.id}.mp3`
        "
      />
    </audio>
  </div>
</template>

<script>
import {
  defineComponent,
  computed,
  reactive,
  toRefs,
  ref,
  onMounted,
  getCurrentInstance,
  watch,
} from "vue";
import { useStore, mapGetters } from "vuex";
import { useRouter } from "vue-router";
import { completeFormatDate } from "@/utils/formate.js";
import { handleSongDetail } from "@/network/musiccontrol/musiccontrol.js";

export default defineComponent({
  name: "MusicControl",
  setup() {
    const store = useStore();
    const router = useRouter();
    let { proxy } = getCurrentInstance();
    // 获取当前播放歌曲的信息
    let currentPlaySong = computed(
      mapGetters(["getCurrentPlaySong"]).getCurrentPlaySong.bind({
        $store: store,
      })
    );
    // 获取保存在vuex中的播放列表
    let songs = computed(
      mapGetters(["getSongs"]).getSongs.bind({
        $store: store,
      })
    );
    let data = reactive({
      playIcon: "", // 播放图标
      nowTime: "00:00", // 音乐播放开始事件
      allTime: "00:00", // 音乐总时间
      id: 0, // 当前播放音乐id
      funcIcon: {
        key: "顺序播放",
        value: "",
      }, // 顺序播放等播放功能图标
      songDetail: {}, // 歌曲详情信息
    });
    let processBar = ref(null); // 进度条总长度的dom
    let processBarChild = ref(null); // 随着歌曲播放的进度条的dom
    let audio = ref(null); // 音乐dom
    let circule = ref(null); // 进度条圆圈
    let volumeBar = ref(null); // 音量条dom
    let volumeBarChild = ref(null); // 音量调内嵌dom
    let volumeCircule = ref(null); // 音量条圆圈

    onMounted(() => {
      if (Object.keys(currentPlaySong.value).length != 0) {
        getSongDetail({ ids: currentPlaySong.value.id });
        data.id = currentPlaySong.value.id;
        data.allTime = completeFormatDate(
          new Date(currentPlaySong.value.dt),
          "mm:ss"
        );
      }
    });

    // 监听当前播放歌曲发生变化
    watch(
      () => currentPlaySong.value,
      () => {
        audio.value.pause();
        data.playIcon = "";
        data.nowTime = "00:00";
        data.allTime = "00:00";
        processBarChild.value.style.width = 0;
        if (songs.value.length !== 0) {
          getSongDetail({ ids: currentPlaySong.value.id });
          data.id = currentPlaySong.value.id;
          data.playIcon = "";

          data.allTime = completeFormatDate(
            new Date(currentPlaySong.value.dt),
            "mm:ss"
          );
          setTimeout(() => {
            let re = /^\d+(\.\d+)?$/;
            if (!re.test(audio.value.duration)) {
              proxy.$message.show({
                title: "因版权原因，不可播放",
                type: "error",
              });
              nextClick();
              return;
            }
            audio.value.play();
          }, 1000);
          return;
        }
        data.id = 0;
        data.songDetail = {};
      }
    );

    // 歌曲详情请求
    let getSongDetail = async (params) => {
      let res = await handleSongDetail(params);
      data.songDetail = res.songs[0];
    };

    // 监听音乐播放过程事件
    let audioTimeUpdate = () => {
      if (songs.value.length == 0) {
        return;
      }

      // 保存播放的时间给歌词组件使用
      store.dispatch("savePlaySongCurrentTime", audio.value.currentTime);

      let processWidth = processBar.value.offsetWidth;
      let currentTime =
        (audio.value.currentTime / audio.value.duration) * processWidth;
      processBarChild.value.style.width = currentTime + "px";
      data.nowTime = timeFormat(audio.value.currentTime);
      if (currentTime >= processWidth) {
        data.playIcon = "";
        audio.value.pause();
      }
    };

    // 监听音乐播放结束回调
    let audioEnded = () => {
      if (data.funcIcon.key == "循环播放") {
        data.playIcon = "";
        data.nowTime = "00:00";
        processBarChild.value.style.width = 0;
        audio.value.play();
        return;
      }

      if (data.funcIcon.key == "顺序播放") {
        nextClick();
        return;
      }

      // 随机播放
      let random = randomFrom(1, songs.value.length);
      store.dispatch("changeCurrentPlaySong", songs.value[random]);
    };

    // 点击播放按钮播放事件
    let btnClick = () => {
      if (Object.keys(currentPlaySong.value).length == 0) {
        proxy.$message.show({
          title: "当前播放列表无音乐",
          type: "info",
        });
        return;
      }
      if (audio.value.paused) {
        // 当继续播放时，判断音乐是否已经播放完毕
        if (audio.value.currentTime >= audio.value.duration) {
          data.nowTime = "00:00";
          processBarChild.value.style.width = 0;
        }
        data.playIcon = "";
        audio.value.play();
      } else {
        data.playIcon = "";
        audio.value.pause();
      }
    };

    // 点击顺序播放等播放功能dom回调
    let funcClick = () => {
      switch (data.funcIcon.key) {
        case "顺序播放":
          data.funcIcon = {
            key: "循环播放",
            value: "",
          };
          break;
        case "循环播放":
          data.funcIcon = {
            key: "随机播放",
            value: "",
          };
          break;

        case "随机播放":
          data.funcIcon = {
            key: "顺序播放",
            value: "",
          };
          break;
        default:
          break;
      }
    };

    // 点击进度条事件
    let processBarClick = (e) => {
      e.stopPropagation();
      let pagex = e.pageX;
      let proBarLeft = processBar.value.offsetLeft;
      let resultX = pagex - proBarLeft;
      processBarChild.value.style.width = resultX + "px";
      audio.value.currentTime =
        (resultX * audio.value.duration) / processBar.value.offsetWidth;
    };

    // 按住进度条上面的小圆圈事件
    let circuleMouseDown = (event) => {
      audio.value.pause();
      event.stopPropagation();
      let pagex = event.pageX;
      let cirLeft = circule.value.offsetLeft;
      let resultX = pagex - cirLeft;
      document.addEventListener("mousemove", move);
      function move(e) {
        let left = e.pageX - resultX;
        if (left > 0 && left <= processBar.value.offsetWidth) {
          processBarChild.value.style.width = left + "px";
          audio.value.currentTime =
            (left * audio.value.duration) / processBar.value.offsetWidth;
        }
      }
      document.addEventListener("mouseup", function () {
        document.removeEventListener("mousemove", move);
        if (data.playIcon == "") {
          audio.value.play();
        }
      });
    };

    // 点击上一首播放
    let prevClick = () => {
      if (songs.value.length == 0) {
        proxy.$message.show({
          title: "播放列表无音乐",
          type: "info",
        });
        return;
      }

      if (songs.value.length == 1) {
        return;
      }

      let i;
      songs.value.find((ele, index) => {
        if (ele.id == currentPlaySong.value.id) {
          i = index;
          return;
        }
      });
      if (i == 0) {
        store.dispatch(
          "changeCurrentPlaySong",
          songs.value[songs.value.length - 1]
        );
        return;
      }

      store.dispatch("changeCurrentPlaySong", songs.value[i - 1]);
    };

    // 点击下一首播放
    let nextClick = () => {
      if (songs.value.length == 0) {
        proxy.$message.show({
          title: "播放列表无音乐",
          type: "info",
        });
        return;
      }

      if (songs.value.length == 1) {
        return;
      }

      let i;
      songs.value.find((ele, index) => {
        if (ele.id == currentPlaySong.value.id) {
          i = index;
          return;
        }
      });

      if (i == songs.value.length - 1) {
        store.dispatch("changeCurrentPlaySong", songs.value[0]);
        return;
      }
      store.dispatch("changeCurrentPlaySong", songs.value[i + 1]);
    };

    // 音量条点击回调
    let volumeBarClick = (e) => {
      e.stopPropagation();
      let pagex = e.pageX;
      let barLeft = volumeBar.value.offsetLeft;
      let resultX = pagex - barLeft;
      volumeBarChild.value.style.width = resultX + "px";
      audio.value.volume = parseFloat(
        (resultX / volumeBar.value.offsetWidth).toFixed(1)
      );
    };

    // 按住音量条圆圈事件
    let volumeCirculeMousedown = (event) => {
      event.stopPropagation();
      var pagex = event.pageX;
      var roundLeft = volumeCircule.value.offsetLeft;
      var resultX = pagex - roundLeft;
      document.addEventListener("mousemove", move);
      function move(e) {
        var right = e.pageX - resultX;
        if (right > 0 && right <= volumeBar.value.offsetWidth) {
          volumeBarChild.value.style.width = right + "px";
          audio.value.volume = parseFloat(
            (right / volumeBar.value.offsetWidth).toFixed(1)
          );
        }
      }
      document.addEventListener("mouseup", function (e) {
        document.removeEventListener("mousemove", move);
      });
    };

    // 点击播放列表回调
    let musicListClick = () => {
      store.dispatch("changeMusicListState");
    };

    // 计算音乐时间方法
    let timeFormat = (number) => {
      let minute = parseInt(number / 60);
      let second = parseInt(number % 60);
      minute = minute >= 10 ? minute : "0" + minute;
      second = second >= 10 ? second : "0" + second;
      return minute + ":" + second;
    };

    // 根据指定的最小值，和最大值，生成一个随机整数
    let randomFrom = (min, max) => {
      return Math.floor(Math.random() * (max - min + 1) + min);
    };

    // 跳转歌词路由
    let goToLyric = () => {
      router.push("/lyric");
    };

    return {
      ...toRefs(data),
      processBar,
      processBarChild,
      circule,
      audio,
      volumeBar,
      volumeBarChild,
      volumeCircule,
      currentPlaySong,
      audioTimeUpdate,
      btnClick,
      audioEnded,
      funcClick,
      processBarClick,
      circuleMouseDown,
      prevClick,
      nextClick,
      volumeBarClick,
      volumeCirculeMousedown,
      musicListClick,
      goToLyric,
    };
  },
});
</script>
<style scoped>
.music_control {
  width: 100%;
  height: 65px;

  position: fixed;
  left: 0;
  bottom: 0;

  background-color: #222;

  z-index: 999;

  -webkit-user-select: none;

  -moz-user-select: none;

  -ms-user-select: none;

  user-select: none;

  border-top: 3px solid #c20c0c;
}
.main {
  width: 70%;
  height: 100%;
  margin: 0 auto;

  display: flex;
  align-items: center;
}
.pic {
  width: 18%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pic_url {
  width: 60px;
  height: 60px;
  border: 3px solid #222;
  cursor: pointer;
}
.name_ar {
  flex: 1;
  margin-left: 8px;
  overflow: hidden;
}
.name,
.ar {
  width: 100%;
  font-size: 14px;
  color: #e2e2e2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ar {
  font-size: 13px;
}

.method {
  width: 18%;
  display: flex;
  align-items: center;
  font-size: 20px;
  color: #fff;
  padding: 0 15px;
  cursor: pointer;
}

.music_list {
  margin-left: 22px;
}

.volume {
  width: 100%;
  display: flex;
  align-items: center;
  margin-left: 22px;
}

.volume_bar {
  flex: 1;
  height: 4px;
  border-radius: 4px;
  background-color: #ccc;
  cursor: pointer;
}

.volume_bar_child {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 4px;
  background-color: #ec4141;
}
.process {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.control span {
  font-size: 20px;
  color: #fff;
  padding: 0 15px;
  cursor: pointer;
}
.process_bar {
  position: relative;
  width: 80%;
  height: 4px;
  margin: 0 auto;
  margin-top: 6px;
  background-color: #ccc;
  border-radius: 4px;
  cursor: pointer;
}

.process_bar_child {
  position: relative;
  width: 0;
  height: 100%;
  background-color: #ec4141;
  border-radius: 4px;
}
.circule,
.volume_circule {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  background-color: #ec4141;
}
.music_time {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  color: #999;
  margin-top: 4px;
}
</style>
